/**
 *  This file is part of Bioinformatics Sequence Comparison Game.
 *
 *  Bioinformatics Sequence Comparison Game is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Bioinformatics Sequence Comparison Game is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Bioinformatics Sequence Comparison Game.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  @author Eric Augustine
 *  @author Jim Jensen
 *  @author Spencer Vanderpoel
 *  @author Corban McCammon
 *  @author Brett Penza
 *  @version 0.1.1
 */
package com.project.BSCG1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Stack;

/*
 * Game data structure holds all methods and initialization of the game
 */
public class Game{
	private ArrayList<Player> players = new ArrayList<Player>(); //Holds all players in the game
	private boolean ending = false; //True if a knock was initiated
	private Deck deck;
	private DiscardPile discardPile;
	private Player knockingPlayer; //Holds the player that initiated the knock
	
	/*
	 * Initializes a game with a certain number of players and their associated names.
	 * Also, initializes the Deck, players hands, and DiscardPile.
	 */
	public Game(int numOfPlayers, ArrayList<String> names){
		deck = new Deck();
		for(int i = 0; i < numOfPlayers; i++){
			String newplayer = names.get(i);
			players.add(new Player(newplayer, i+1));
		}
		
		ArrayList<Hand> hands = deck.deal(numOfPlayers);
		for(int i = 0; i < players.size(); i++){
			players.get(i).setPlayersHand(hands.get(i));
			players.get(i).getPlayersHand().setUpTurnUp(numOfPlayers);
		}
		discardPile = new DiscardPile(deck);
	}
	
	public ArrayList<Player> getPlayers(){
		return players;
	}
	
	public void setPlayers(Player player, int position){
		players.set(position, player);
	}
	
	public Deck getDeck(){
		return deck;
	}
	
	public void setDeck(Deck newDeck){
		deck = newDeck;
	}
	
	public DiscardPile getDiscardPile(){
		return discardPile;
	}
	
	public void setDiscardPile(DiscardPile newDiscardPile){
		discardPile = newDiscardPile;
	}
	/* 
	 * Signals a knock from a given player
	 */
	public void knock(Player player){
		knockingPlayer = player;
	}
	
	public Player getKnockingPlayer(){
		return knockingPlayer;
	}
}

/*
 * Data Structure for all player related information, including Hand, playerNum,
 * userName, score, whether they knocked
 */
class Player{
	private Hand playersHand;
	private int playerNumber;
	private String userName;
	private int cardsPicked = 0;
	private int score = 0;
	private boolean knocked = false;
	private boolean firstTurn = true;
	private boolean firstDraw = true;
	private boolean firstDiscard = true;
	
	/*
	 * Initializes userName and playerNum
	 */
	public Player(String name, int number){
		userName = name;
		playerNumber = number;
	}
	
	/*
	 * Setter for score
	 */
	public void setScore(int newScore){
		score = newScore;
	}
	
	/*
	 * Getter for score
	 */
	public int getScore(){
		return score;
	}
	
	public int getCardsPicked(){
		return cardsPicked;
	}
	
	public void incrementCardsPicked(){
		cardsPicked++;
	}
	
	public void setCardsPicked(int val){
		cardsPicked = val;
	}
	
	/*
	 * Getter for userName
	 */
	public String getUserName(){
		return userName;
	}
	
	/*
	 * Setter for userName
	 */
	public void setUserName(String s){
		userName = s;
	}
	
	/*
	 * Getter for playerNum
	 */
	public int getPlayerNumber(){
		return playerNumber;
	}
	
	/*
	 * Setter for knocked
	 */
	public void setKnocked(boolean knock){
		knocked = knock;
	}
	
	/*
	 * Getter for knocked
	 */
	public boolean getKnocked(){
		return knocked;
	}
	
	/*
	 * Getter for playersHand
	 */
	public Hand getPlayersHand(){
		return playersHand;
	}
	
	/*
	 * Setter for playersHand
	 */
	public void setPlayersHand(Hand newHand){
		playersHand = newHand;
	}
	
	public boolean getFirstTurn(){
		return firstTurn;
	}
	
	public boolean getFirstDraw(){
		return firstDraw;
	}
	
	public boolean getFirstDiscard(){
		return firstDiscard;
	}
	
	public void setFirstTurn(boolean ft){
		firstTurn = ft;
	}
	
	public void setFirstDraw(boolean fd){
		firstDraw = fd;
	}
	
	public void setFirstDiscard(boolean fd){
		firstDiscard = fd;
	}
	
	public void updateScore(Score map){
		ArrayList<String> adjCards = playersHand.currentAdjacentCardsFaceUp();
    	this.score = map.currentScore(adjCards);
	}
}

/*
 * Parent class of deck and pile contains a stack of Cards and methods for the stack
 */
abstract class Pile{
	private Stack<Card> pile = new Stack<Card>();
	
	
	/*
	 * Pops the top card off the pile
	 */
	public Card drawCard(){
		return pile.pop();
	}
	
	/*
	 * Pushes a card on the pile
	 */
	public void pushCard(Card nextCard){
		pile.push(nextCard);
	}
	
	/*
	 * Reveals the top card on the pile
	 */
	public Card peekAtTop(){
		return pile.peek();
	}
	
	public boolean isEmpty(){
		return pile.isEmpty();
	}
	
	/*
	 * Returns the size of the pile
	 */
	public int size(){
		return pile.size();
	}
	
}

/*
 * Data structure for a Deck, contains the Deck (pile in parent class). Also, contains an array of the 20
 * common amino acids (values for cards in the deck) and the frequency of which they occur in the deck
 */
class Deck extends Pile{
	
	//20 common amino acids represented as a single char String
	String[] aminoAcids = {"A","R","N","D","C","Q","E","G","H","I","L","K","M","F","P","S","T","W","Y","V"};
	
	//Frequency at which each amino acid occurs in the deck such that aminoAcids[0] occurs acidFrequency[0]
	int[] acidFrequency = {7,5,4,5,3,4,6,7,3,6,9,6,2,4,5,7,6,2,4,7};
	
	/*
	 * Initializes deck
	 */
	public Deck(){
		shuffle();
	}
	
	/*
	 * Puts 100 cards corresponding to the amino acids on the Deck randomly
	 * until it reaches its maximum frequency, then those at their maximum frequency
	 * are skipped
	 */
	private void shuffle(){
		ArrayList<Card> list = new ArrayList<Card>();
		for(int i = 0; i < aminoAcids.length; i++) {
			for (int j = acidFrequency[i]; j > 0; j--)
				list.add(new Card(aminoAcids[i]));
		}
		Collections.shuffle(list);
		Collections.shuffle(list);
		while(! list.isEmpty()) { // put the deck from the list into the stack
			pushCard(list.get(list.size() - 1));
			list.remove(list.size() - 1);
		}
	}
	
	/*
	 * Deals cards to each players hand from the deck
	 */
	public ArrayList<Hand> deal(int numOfPlayers){
		ArrayList<Hand> playersHands = new ArrayList<Hand>(numOfPlayers);
		int numOfCards = 0;
		switch(numOfPlayers){
			case 1:
				numOfCards = 16;
				break;
			case 2:
				numOfCards = 12;
				break;
			case 3:
				numOfCards = 10;
				break;
			case 4:
				numOfCards = 8;
				break;
			default:
				break;
		}
		
		for(int i = 0; i < numOfPlayers; i++){
			Hand hand = new Hand();
			for(int j = 0; j < numOfCards; j++){
				hand.addCard(drawCard());
			}
			playersHands.add(hand);
		}
		
		return playersHands;
	}
}

/*
 * Data Structure for the Discard Pile
 */
class DiscardPile extends Pile{
	DiscardPile(){
	}
	
	/*
	 * Initializes the discardPile to the top card of the deck
	 */
	DiscardPile(Deck d){
		pushCard(d.drawCard());
	}
	
}

/*
 * Data Structure for the hand contains a arraylist of cards and methods on 
 * the arraylist
 */
class Hand{
	private ArrayList<Card> hand = new ArrayList<Card>();
	private boolean[] turnUp;
	public Hand(){
		
	}
	
	/*
	 * Getter for a card from the hand at a specific index
	 */
	public Card getCard(int index){
		return hand.get(index);
	}
	
	/*
	 * Adds a card to the last position in the hand
	 */
	public void addCard(Card card){
		hand.add(card);
	}
	
	public boolean[] getTurnUp(){
		return turnUp;
	}
	
	public ArrayList<String> currentAdjacentCardsFaceUp(){
		ArrayList<String> currentCardsUp = new ArrayList<String>();
		int length = (int)(turnUp.length / 2.0);
		for(int i = 0; i < length; i++){
			if(turnUp[i]){
				if(turnUp[length + i]){
					currentCardsUp.add(hand.get(i).getAminoAcid());
					currentCardsUp.add(hand.get(length + i).getAminoAcid());
				}
			}
		}
		
		return currentCardsUp;
	}
	
	/*
	 * Replaces a card with a newCard at a given position in the hand
	 */
	public Card replaceCard(Card newCard, int position){
		Card oldCard = hand.get(position);
		hand.set(position, newCard);
		return oldCard;
	}
	
	public void setCardTurn(int position) {
		turnUp[position] = true; 
	}
	
	public void setUpTurnUp(int numOfPlayers){
		switch(numOfPlayers){
			case 1:
				turnUp = new boolean [16];
				for(int i = 0; i < turnUp.length; i++){
					turnUp[i] = false;
				}
				break;
			case 2:
				turnUp = new boolean [12];
				for(int i = 0; i < turnUp.length; i++){
					turnUp[i] = false;
				}
				break;
			case 3:
				turnUp = new boolean [10];
				for(int i = 0; i < turnUp.length; i++){
					turnUp[i] = false;
				}
				break;
			case 4:
				turnUp = new boolean [8];
				for(int i = 0; i < turnUp.length; i++){
					turnUp[i] = false;
				}
				break;
		}
	}
	
	public boolean getCardTurn(int position) {
		return turnUp[position];
	}
	
	/*
	 * Returns size of hand
	 */
	public int size(){
		return hand.size();
	}
}

/*
 * Data structure for a card
 */
class Card{
	private String aminoAcid; //Amino acid value ex. "A"
	
	/*
	 * Initializes aminoAcid
	 */
	public Card(String aAcid){
		aminoAcid = aAcid;
	}
	
	/*
	 * Getter for aminoAcid
	 */
	public String getAminoAcid(){
		return aminoAcid;
	}
	
	/*
	 * Setter for aminoAcid
	 */
	public void setAminoAcid(String aAcid){
		aminoAcid = aAcid;
	}
	
}

/*
 * Contains the scoreMap for the scoring of a given hand
 */
class Score{

    HashMap<String, Integer> scoreMap = new HashMap<String, Integer>();

    /*
     * Initialize all the values of the scoreMap
     */
    public Score(){
        // 'V' row
        scoreMap.put("AV", -2);
        scoreMap.put("RV", -8);
        scoreMap.put("NV", -8);
        scoreMap.put("DV", -8);
        scoreMap.put("CV", -6);
        scoreMap.put("QV", -7);
        scoreMap.put("EV", -6);
        scoreMap.put("GV", -5);
        scoreMap.put("HV", -6);
        scoreMap.put("IV", 2);
        scoreMap.put("LV", -2);
        scoreMap.put("KV", -9);
        scoreMap.put("MV", -1);
        scoreMap.put("FV", -8);
        scoreMap.put("PV", -6);
        scoreMap.put("SV", -6);
        scoreMap.put("TV", -3);
        scoreMap.put("WV", -15);
        scoreMap.put("YV", -7);
        scoreMap.put("VV", 7);
        // 'V' row transposed
        scoreMap.put("VA", -2);
        scoreMap.put("VR", -8);
        scoreMap.put("VN", -8);
        scoreMap.put("VD", -8);
        scoreMap.put("VC", -6);
        scoreMap.put("VQ", -7);
        scoreMap.put("VE", -6);
        scoreMap.put("VG", -5);
        scoreMap.put("VH", -6);
        scoreMap.put("VI", 2);
        scoreMap.put("VL", -2);
        scoreMap.put("VK", -9);
        scoreMap.put("VM", -1);
        scoreMap.put("VF", -8);
        scoreMap.put("VP", -6);
        scoreMap.put("VS", -6);
        scoreMap.put("VT", -3);
        scoreMap.put("VW", -15);
        scoreMap.put("VY", -7);
        
        // 'Y' row
        scoreMap.put("AY", -8);
        scoreMap.put("RY", -10);
        scoreMap.put("NY", -4);
        scoreMap.put("DY", -11);
        scoreMap.put("CY", -4);
        scoreMap.put("QY", -12);
        scoreMap.put("EY", -8);
        scoreMap.put("GY", -14);
        scoreMap.put("HY", -3);
        scoreMap.put("IY", -6);
        scoreMap.put("LY", -7);
        scoreMap.put("KY", -9);
        scoreMap.put("MY", -11);
        scoreMap.put("FY", 2);
        scoreMap.put("PY", -13);
        scoreMap.put("SY", -7);
        scoreMap.put("TY", -6);
        scoreMap.put("WY", -5);
        scoreMap.put("YY", 10);
        // 'Y' row transposed
        scoreMap.put("YA", -8);
        scoreMap.put("YR", -10);
        scoreMap.put("YN", -4);
        scoreMap.put("YD", -11);
        scoreMap.put("YC", -4);
        scoreMap.put("YQ", -12);
        scoreMap.put("YE", -8);
        scoreMap.put("YG", -14);
        scoreMap.put("YH", -3);
        scoreMap.put("YI", -6);
        scoreMap.put("YL", -7);
        scoreMap.put("YK", -9);
        scoreMap.put("YM", -11);
        scoreMap.put("YF", 2);
        scoreMap.put("YP", -13);
        scoreMap.put("YS", -7);
        scoreMap.put("YT", -6);
        scoreMap.put("YW", -5);
        
        // 'W' row
        scoreMap.put("AW", -13);
        scoreMap.put("RW", -2);
        scoreMap.put("NW", -8);
        scoreMap.put("DW", -15);
        scoreMap.put("CW", -15);
        scoreMap.put("QW", -13);
        scoreMap.put("EW", -17);
        scoreMap.put("GW", -15);
        scoreMap.put("HW", -7);
        scoreMap.put("IW", -14);
        scoreMap.put("LW", -6);
        scoreMap.put("KW", -12);
        scoreMap.put("MW", -13);
        scoreMap.put("FW", -4);
        scoreMap.put("PW", -14);
        scoreMap.put("SW", -5);
        scoreMap.put("TW", -13);
        scoreMap.put("WW", 13);
        // 'W' row transposed
        scoreMap.put("WA", -13);
        scoreMap.put("WR", -2);
        scoreMap.put("WN", -8);
        scoreMap.put("WD", -15);
        scoreMap.put("WC", -15);
        scoreMap.put("WQ", -13);
        scoreMap.put("WE", -17);
        scoreMap.put("WG", -15);
        scoreMap.put("WH", -7);
        scoreMap.put("WI", -14);
        scoreMap.put("WL", -6);
        scoreMap.put("WK", -12);
        scoreMap.put("WM", -13);
        scoreMap.put("WF", -4);
        scoreMap.put("WP", -14);
        scoreMap.put("WS", -5);
        scoreMap.put("WT", -13);
        
        // 'T' row
        scoreMap.put("AT", -1);
        scoreMap.put("RT", -6);
        scoreMap.put("NT", -2);
        scoreMap.put("DT", -5);
        scoreMap.put("CT", -8);
        scoreMap.put("QT", -5);
        scoreMap.put("ET", -6);
        scoreMap.put("GT", -6);
        scoreMap.put("HT", -7);
        scoreMap.put("IT", -2);
        scoreMap.put("LT", -7);
        scoreMap.put("KT", -3);
        scoreMap.put("MT", -4);
        scoreMap.put("FT", -9);
        scoreMap.put("PT", -4);
        scoreMap.put("ST", 0);
        scoreMap.put("TT", 7);
        // 'T' row transposed
        scoreMap.put("TA", -1);
        scoreMap.put("TR", -6);
        scoreMap.put("TN", -2);
        scoreMap.put("TD", -5);
        scoreMap.put("TC", -8);
        scoreMap.put("TQ", -5);
        scoreMap.put("TE", -6);
        scoreMap.put("TG", -6);
        scoreMap.put("TH", -7);
        scoreMap.put("TI", -2);
        scoreMap.put("TL", -7);
        scoreMap.put("TK", -3);
        scoreMap.put("TM", -4);
        scoreMap.put("TF", -9);
        scoreMap.put("TP", -4);
        scoreMap.put("TS", 0);
        
        // 'S' row
        scoreMap.put("AS", 0);
        scoreMap.put("RS", -3);
        scoreMap.put("NS", 0);
        scoreMap.put("DS", -4);
        scoreMap.put("CS", -3);
        scoreMap.put("QS", -5);
        scoreMap.put("ES", -4);
        scoreMap.put("GS", -2);
        scoreMap.put("HS", -6);
        scoreMap.put("IS", -7);
        scoreMap.put("LS", -8);
        scoreMap.put("KS", -4);
        scoreMap.put("MS", -5);
        scoreMap.put("FS", -6);
        scoreMap.put("PS", -2);
        scoreMap.put("SS", 6);
        // 'S' row transposed
        scoreMap.put("SA", 0);
        scoreMap.put("SR", -3);
        scoreMap.put("SN", 0);
        scoreMap.put("SD", -4);
        scoreMap.put("SC", -3);
        scoreMap.put("SQ", -5);
        scoreMap.put("SE", -4);
        scoreMap.put("SG", -2);
        scoreMap.put("SH", -6);
        scoreMap.put("SI", -7);
        scoreMap.put("SL", -8);
        scoreMap.put("SK", -4);
        scoreMap.put("SM", -5);
        scoreMap.put("SF", -6);
        scoreMap.put("SP", -2);
        
        // 'P' row
        scoreMap.put("AP", -2);
        scoreMap.put("RP", -4);
        scoreMap.put("NP", -6);
        scoreMap.put("DP", -8);
        scoreMap.put("CP", -8);
        scoreMap.put("QP", -3);
        scoreMap.put("EP", -5);
        scoreMap.put("GP", -6);
        scoreMap.put("HP", -4);
        scoreMap.put("IP", -8);
        scoreMap.put("LP", -7);
        scoreMap.put("KP", -6);
        scoreMap.put("MP", -8);
        scoreMap.put("FP", -10);
        scoreMap.put("PP", 8);
        // 'P' row transposed
        scoreMap.put("PA", -2);
        scoreMap.put("PR", -4);
        scoreMap.put("PN", -6);
        scoreMap.put("PD", -8);
        scoreMap.put("PC", -8);
        scoreMap.put("PQ", -3);
        scoreMap.put("PE", -5);
        scoreMap.put("PG", -6);
        scoreMap.put("PH", -4);
        scoreMap.put("PI", -8);
        scoreMap.put("PL", -7);
        scoreMap.put("PK", -6);
        scoreMap.put("PM", -8);
        scoreMap.put("PF", -10);
        
        // 'F' row
        scoreMap.put("AF", -8);
        scoreMap.put("RF", -9);
        scoreMap.put("NF", -9);
        scoreMap.put("DF", -15);
        scoreMap.put("CF", -13);
        scoreMap.put("QF", -13);
        scoreMap.put("EF", -14);
        scoreMap.put("GF", -9);
        scoreMap.put("HF", -6);
        scoreMap.put("IF", -2);
        scoreMap.put("LF", -3);
        scoreMap.put("KF", -14);
        scoreMap.put("MF", -4);
        scoreMap.put("FF", 9);
        // 'F' row transposed
        scoreMap.put("FA", -8);
        scoreMap.put("FR", -9);
        scoreMap.put("FN", -9);
        scoreMap.put("FD", -15);
        scoreMap.put("FC", -13);
        scoreMap.put("FQ", -13);
        scoreMap.put("FE", -14);
        scoreMap.put("FG", -9);
        scoreMap.put("FH", -6);
        scoreMap.put("FI", -2);
        scoreMap.put("FL", -3);
        scoreMap.put("FK", -14);
        scoreMap.put("FM", -4);
        
        // 'M' row
        scoreMap.put("AM", -5);
        scoreMap.put("RM", -4);
        scoreMap.put("NM", -9);
        scoreMap.put("DM", -11);
        scoreMap.put("CM", -13);
        scoreMap.put("QM", -4);
        scoreMap.put("EM", -7);
        scoreMap.put("GM", -8);
        scoreMap.put("HM", -10);
        scoreMap.put("IM", -1);
        scoreMap.put("LM", 1);
        scoreMap.put("KM", -2);
        scoreMap.put("MM", 11);
        // 'M' row transposed
        scoreMap.put("MA", -5);
        scoreMap.put("MR", -4);
        scoreMap.put("MN", -9);
        scoreMap.put("MD", -11);
        scoreMap.put("MC", -13);
        scoreMap.put("MQ", -4);
        scoreMap.put("ME", -7);
        scoreMap.put("MG", -8);
        scoreMap.put("MH", -10);
        scoreMap.put("MI", -1);
        scoreMap.put("ML", 1);
        scoreMap.put("MK", -2);
        
        // 'K' row
        scoreMap.put("AK", -7);
        scoreMap.put("RK", 0);
        scoreMap.put("NK", -1);
        scoreMap.put("DK", -4);
        scoreMap.put("CK", -14);
        scoreMap.put("QK", -3);
        scoreMap.put("EK", -4);
        scoreMap.put("GK", -7);
        scoreMap.put("HK", -6);
        scoreMap.put("IK", -6);
        scoreMap.put("LK", -8);
        scoreMap.put("KK", 7);
        // 'K' row transposed
        scoreMap.put("KA", -7);
        scoreMap.put("KR", 0);
        scoreMap.put("KN", -1);
        scoreMap.put("KD", -4);
        scoreMap.put("KC", -14);
        scoreMap.put("KQ", -3);
        scoreMap.put("KE", -4);
        scoreMap.put("KG", -7);
        scoreMap.put("KH", -6);
        scoreMap.put("KI", -6);
        scoreMap.put("KL", -8);
        
        // 'L' row
        scoreMap.put("AL", -6);
        scoreMap.put("RL", -8);
        scoreMap.put("NL", -7);
        scoreMap.put("DL", -12);
        scoreMap.put("CL", -15);
        scoreMap.put("QL", -5);
        scoreMap.put("EL", -9);
        scoreMap.put("GL", -10);
        scoreMap.put("HL", -6);
        scoreMap.put("IL", -1);
        scoreMap.put("LL", 7);
        // 'L' row transposed
        scoreMap.put("LA", -6);
        scoreMap.put("LR", -8);
        scoreMap.put("LN", -7);
        scoreMap.put("LD", -12);
        scoreMap.put("LC", -15);
        scoreMap.put("LQ", -5);
        scoreMap.put("LE", -9);
        scoreMap.put("LG", -10);
        scoreMap.put("LH", -6);
        scoreMap.put("LI", -1);
        
        // 'I' row
        scoreMap.put("AI", -5);
        scoreMap.put("RI", -5);
        scoreMap.put("NI", -5);
        scoreMap.put("DI", -7);
        scoreMap.put("CI", -6);
        scoreMap.put("QI", -8);
        scoreMap.put("EI", -5);
        scoreMap.put("GI", -11);
        scoreMap.put("HI", -9);
        scoreMap.put("II", 8);
        // 'I' row transposed
        scoreMap.put("IA", -5);
        scoreMap.put("IR", -5);
        scoreMap.put("IN", -5);
        scoreMap.put("ID", -7);
        scoreMap.put("IC", -6);
        scoreMap.put("IQ", -8);
        scoreMap.put("IE", -5);
        scoreMap.put("IG", -11);
        scoreMap.put("IH", -9);
        
        // 'H' row
        scoreMap.put("AH", -7);
        scoreMap.put("RH", -2);
        scoreMap.put("NH", 0);
        scoreMap.put("DH", -4);
        scoreMap.put("CH", -7);
        scoreMap.put("QH", 1);
        scoreMap.put("EH", -5);
        scoreMap.put("GH", -9);
        scoreMap.put("HH", 9);
        // 'H' row transposed
        scoreMap.put("HA", -7);
        scoreMap.put("HR", -2);
        scoreMap.put("HN", 0);
        scoreMap.put("HD", -4);
        scoreMap.put("HC", -7);
        scoreMap.put("HQ", 1);
        scoreMap.put("HE", -5);
        scoreMap.put("HG", -9);
        
        // 'G' row
        scoreMap.put("AG", -2);
        scoreMap.put("RG", -9);
        scoreMap.put("NG", -3);
        scoreMap.put("DG", -3);
        scoreMap.put("CG", -9);
        scoreMap.put("QG", -7);
        scoreMap.put("EG", -4);
        scoreMap.put("GG", 6);
        // 'G' row transposed
        scoreMap.put("GA", -2);
        scoreMap.put("GR", -9);
        scoreMap.put("GN", -3);
        scoreMap.put("GD", -3);
        scoreMap.put("GC", -9);
        scoreMap.put("GQ", -7);
        scoreMap.put("GE", -4);
        
        // 'E' row
        scoreMap.put("AE", -2);
        scoreMap.put("RE", -9);
        scoreMap.put("NE", -2);
        scoreMap.put("DE", 2);
        scoreMap.put("CE", -14);
        scoreMap.put("QE", 1);
        scoreMap.put("EE", 8);
        // 'E' row transposed
        scoreMap.put("EA", -2);
        scoreMap.put("ER", -9);
        scoreMap.put("EN", -2);
        scoreMap.put("ED", 2);
        scoreMap.put("EC", -14);
        scoreMap.put("EQ", 1);
        
        // 'Q' row
        scoreMap.put("AQ", -4);
        scoreMap.put("RQ", -2);
        scoreMap.put("NQ", -3);
        scoreMap.put("DQ", -2);
        scoreMap.put("CQ", -14);
        scoreMap.put("QQ", 8);
        // 'Q' row transposed
        scoreMap.put("QA", -4);
        scoreMap.put("QR", -2);
        scoreMap.put("QN", -3);
        scoreMap.put("QD", -2);
        scoreMap.put("QC", -14);
        
        // 'C' row
        scoreMap.put("AC", -6);
        scoreMap.put("RC", -8);
        scoreMap.put("NC", -11);
        scoreMap.put("DC", -14);
        scoreMap.put("CC", 10);
        // 'C' row transposed
        scoreMap.put("CA", -6);
        scoreMap.put("CR", -8);
        scoreMap.put("CN", -11);
        scoreMap.put("CD", -14);
        
        // 'D' row
        scoreMap.put("AD", -3);
        scoreMap.put("RD", -10);
        scoreMap.put("ND", 2);
        scoreMap.put("DD", 8);
        // 'D' row transposed
        scoreMap.put("DA", -3);
        scoreMap.put("DR", -10);
        scoreMap.put("DN", 2);
        
        // 'N' row
        scoreMap.put("AN", -4);
        scoreMap.put("RN", -6);
        scoreMap.put("NN", 8);
        // 'N' row transposed
        scoreMap.put("NA", -4);
        scoreMap.put("NR", -6);
        
        // 'R' row
        scoreMap.put("AR", -7);
        scoreMap.put("RR", 8);
        // 'R' row transposed
        scoreMap.put("RA", -7);

        // 'A' row
        scoreMap.put("AA", 6);
    }
    
    /*
     * Score the hand of a given player
     */
    public int scoreHand(Player player){
        Hand hand = player.getPlayersHand();
        int half = (hand.size() / 2);
        int totalScore = 0;
        for(int i = 0; i < half; i++){
           totalScore += scoreCombo(hand.getCard(i).getAminoAcid(), (hand.getCard(i + half).getAminoAcid()));
        }
        return totalScore;
    }
    
    public int currentScore(ArrayList<String> validCards){
    	int currentScore = 0;
    	
    	if(validCards.size() > 0){
    		for(int i = 0; i < validCards.size(); i = i + 2){
    			currentScore += scoreCombo(validCards.get(i), validCards.get(i+1));
    		}
    	}
    	
    	return currentScore;
    }
    
    /*
     * Finds a combination of two amino acids in the scoreMap an returns the score associated with it
     */
    private int scoreCombo(String firstAcid, String secondAcid){
        return scoreMap.get(firstAcid + secondAcid);
    }
}

class PlayerAndCard{
	private int playerNum;
	private int cardNum;
	
	public PlayerAndCard(){
	}
	
	public PlayerAndCard(int p){
		playerNum = p;
	}
	
	public PlayerAndCard(int p, int c){
		playerNum = p;
		cardNum = c;
	}
	
	public int getPlayerNum(){
		return playerNum;
	}
	
	public int getCardNum(){
		return cardNum;
	}
	
	public void setPlayerNum(int p){
		playerNum = p;
	}
	
	public void setCardNum(int c){
		cardNum = c;
	}
}
